#include<machine/m_bw.h>
#include<Lcode/l_main.h>
#include"phase1_func.h"
#include"lbw_op_query.h"
#include"../share/predicat.h"
//#include"lbw_intrinsic.h"
#include"lbw_opti.h"

#include"unit_test.h"

#define DEBUG 0



/* phase-1 the Lcode -> mcode annotation 
 */


L_Attr * lineno_attr;

void 
static L_add_lineno_attr(L_Oper *oper)
{
	if(DEBUG)
	{
		L_Attr *new_attr = L_new_attr ("lineno", 1);
		L_set_int_attr_field (new_attr, 0, lineno_attr->field[0]->value.i);
		oper->attr =L_concat_attr (oper->attr, new_attr);
	}
	return ;
}



//insert new_oper that transport src to dest before the oper
L_Oper* Lbw_build_imm_trans_oper (L_Cb * cb, L_Oper * oper,L_Operand * src, L_Operand * dest)
{
	//note for the ITint32 is define in the IMPACT config , the max value is 32
		L_Oper *new_oper;

		if(!L_is_reg(dest))
			L_punt("Lbw_build_imm_trans_oper: error, expected the dest->type is register");
		if(!( (src->type == L_OPERAND_IMMED) || L_is_label(src)) )
			L_punt("Lbw_build_imm_trans_oper: error, oper  expected the src is imm_operand or label " );

		if( bw_is_addr_reg(dest))
		{
			new_oper = L_create_new_op_using (Lop_MOV, oper);
			new_oper->proc_opc = LBWop_MOV_IMM32_ADDR;
		}
		else
		{
			new_oper = L_create_new_op_using (Lop_MOV, oper);	
			new_oper->proc_opc = LBWop_MOV_IMM32_S;
		}

		new_oper->src[0] = L_copy_operand( src );
		new_oper->dest[0] = L_copy_operand( dest );
		L_insert_oper_before (cb, oper, new_oper);
		return (new_oper);
}




static L_Oper* bw_convert_to_parent(L_Cb* cb, L_Oper* oper)
{
/*
	if(bw_is_simd_start(oper))
	{
		L_Oper *xoper = oper;
		while(bw_is_simd_end(xoper))
		{
			xoper = L_convert_to_parent(cb, xoper);
		}
		return L_convert_to_parent(cb, xoper);
	}
*/
	return L_convert_to_parent(cb, oper);
}


static void bw_pre_annotate_simd_load(L_Cb *cb, L_Oper *oper)
{
	L_Oper *xoper = oper->next_op;
	L_Operand *increment = oper->src[0];
	for(xoper = oper->next_op; !bw_is_simd_end(xoper); xoper = xoper->next_op	)
	{
		L_delete_operand(xoper->src[2]);
		xoper->src[2] = L_copy_operand(increment);
	}
}
static void bw_pre_annotate_simd_store(L_Cb *cb, L_Oper*oper)
{
	L_Oper *xoper;
	L_Operand *increment = oper->src[3];
	for(xoper = oper->next_op; !bw_is_simd_end(xoper); xoper = xoper->next_op)
	{
		L_delete_operand(xoper->src[3]);
		xoper->src[3] = L_copy_operand(increment);
	}
}

/*
 * L_annotate_define process the vector simd_oper
 */
static void L_annotate_define(L_Cb* cb, L_Oper *oper)
{	if(bw_is_simd_load(oper))
		bw_pre_annotate_simd_load(cb, oper);
	if(bw_is_simd_store(oper))
		bw_pre_annotate_simd_store(cb, oper);
//	if(!bw_is_simd_start(oper))
	{
		oper->proc_opc = LBWop_NON_INSTR;
		L_insert_oper_before (cb, oper, L_copy_parent_oper (oper));
		return ;
	}
	/*
	if(!bw_is_simd_end(oper))
	{
		oper->proc_opc = LBWop_NON_INSTR;
		L_insert_oper_before(cb, oper, L_copy_parent_oper(oper));
	}
	*/
	/*
	 * now process the simd_opers;
	 */



}
/*
 * note the oper must be define operation
 * 			Lop_DEFINE [ ] [ increment_opd] <simd_start>
 * 				Lop_LOAD [ ] [x, x, x]
 * 				Lop_LOAD [ ] [x, x, x]
 * 					...............
 * 			Lop_DEFINE [ ] [		] 			<simd_end>
 *
 * after annotate of simd operation , no lcode operation is delete, beacause we need
 * the operation to hold the so many operands.
 */


static 
void  L_annotate_same( L_Cb * cb , L_Oper *oper)
{
	L_Oper * new_oper;
	new_oper= L_create_new_op_using (oper->opc,oper);
	L_insert_oper_before(cb,oper, new_oper); 
}

/***
*  case move type : mov [reg][mac]  --->mov [reg][mac]
*  case move type : mov [reg][reg]  ---> mov [reg][reg]
*  case move type : mov [reg][imm] ---> Rs=c or Rs=c(u)
*/
void static
L_annotate_move (L_Cb * cb, L_Oper * oper)
{
	int proc_opc = 0;
	L_Oper *new_oper;
	L_Operand *src, *dest;
	L_Operand * new_src = NULL , * new_dest = NULL;
	L_Operand * imm_src = NULL;
	
	src = oper->src[0];
	dest = oper->dest[0];
	L_print_oper(stdout,oper);	
	if( bw_is_addr_reg(dest))
	{
		switch(src->type)
		{
			case L_OPERAND_IMMED:
			case L_OPERAND_LABEL:
				proc_opc = LBWop_MOV_IMM32_ADDR;
					break;

			case L_OPERAND_REGISTER:
			case L_OPERAND_MACRO:
				if( bw_is_addr_reg(src))
				{//annotate the addr_reg ---> addr_reg == addr_reg == addr_reg + imm_0
					imm_src = L_new_gen_int_operand(0);
					proc_opc = LBWop_ADD_ADDR_IMM8;
				}
				else if(bw_is_data_reg(src))
				{
					proc_opc = LBWop_MOV_GR_ADDR;
				}
				else
				{
					L_punt("L_annotate_mov : error, oper %d the the src operand is not expected",oper->id);
				}
					break;
			default:
				L_punt("L_annotate_mov: error, oper %d the src operand type is not expected", oper->id);
		}
	}
	else if(bw_is_data_reg(dest))
	{
		switch(src->type)
		{
			case L_OPERAND_IMMED:
			case L_OPERAND_LABEL:
				if( oper->opc == Lop_MOV_F || oper->opc == Lop_MOV_F2)
				{
					proc_opc = LBWop_MOV_IMM32_F;
				}
				else
				{
					proc_opc = LBWop_MOV_IMM32_S;
				}
				break;
			case L_OPERAND_MACRO:
			case L_OPERAND_REGISTER:
				if( bw_is_addr_reg(src))
				{
					proc_opc = LBWop_MOV_ADDR_GR;
				}
				else if(bw_is_data_reg(src))
				{
					proc_opc =  LBWop_MOV_GR;
				}
				else
				{
					L_punt("L_annotate_mov: error, op %d the  src operand is not expected ", oper->id);
				}
				break;

			default:
				L_punt("L_annotate_mov: error, op %d the src operand is not expected ",oper->id);
		}
	}
	else
	{
		L_punt("L_annotate_mov: oper %d  please check the dest operand ");
	}
	
	if( new_src == NULL)
	{
		new_src = L_copy_operand( oper->src[0]);
	}

	if( new_dest == NULL)
	{
		new_dest = L_copy_operand( oper->dest[0]);
	}

	new_oper = L_create_new_op_using(oper->opc, oper);
   new_oper->proc_opc = proc_opc;
   new_oper->dest[0] = new_dest;
   new_oper->src[0] = new_src;
	new_oper->src[1] = imm_src;
   L_insert_oper_before(cb, oper, new_oper);
		return ;
}

static 
int  Lbw_should_swap_operand(L_Operand *operand1,L_Operand * operand2)
{                                                       
	/*if src1 is consant and src2 is mac or reg then swap */ 
	if(operand1->type == L_OPERAND_IMMED &&L_is_variable(operand2))
		return 1;
	if(operand1->type == L_OPERAND_LABEL && L_is_variable(operand2))
		return 1;
	if(operand1->type == L_OPERAND_IMMED && L_is_label(operand2))
		return 1;
  return 0;
}

/*****************************************************************************\
 *
 * 						     Addition and Subtraction
 *
\*****************************************************************************/

/*  
*   int add:
*  if ctype of mac or reg operand is pnt ,then as the addr_reg
*   by wxq 10/12/2008
*/ 

//ok
static void L_annotate_add_INT (L_Cb * cb, L_Oper * oper)
{		
	int proc_opc;
	L_Oper *new_oper;
	L_Operand *src0, *src1;
	L_Operand  *new_src0 = NULL;
	L_Operand  *new_src1 = NULL;

	src0 = oper->src[0];
	src1 = oper->src[1];
	
	if(Lbw_should_swap_operand(src0,src1))
	{
		src0=oper->src[1];
		src1=oper->src[0];
	}


	if( bw_is_addr_reg(oper->dest[0]))
	{
		if(bw_is_imm_or_label(src0))
		{
			new_src0 = Lbw_new_addr_reg();
			Lbw_build_imm_trans_oper(cb, oper, src0, new_src0);
		}

		if((src1->type == L_OPERAND_IMMED) && SIMM_8(src1->value.i))
		{
			new_src1 = L_copy_operand(src1);
			proc_opc = LBWop_ADD_ADDR_IMM8;	
		}
		else if( bw_is_imm_or_label(src1))
		{
			new_src1 = Lbw_new_addr_reg();
			Lbw_build_imm_trans_oper(cb, oper, src1, new_src1);
			proc_opc = LBWop_ADD_ADDR;
		}
		else if( bw_is_addr_reg(src1))
		{
			new_src1 = L_copy_operand(src1);
			proc_opc = LBWop_ADD_ADDR;
		}
		else
		{
			L_punt("L_annotate_add_INT: error , oper %d , the src1 is not expected",oper->id);
		}
	}
	else if (bw_is_data_reg(oper->dest[0]))
	{
		//process src0
		if(bw_is_imm_or_label(src0))
		{
			new_src0 = Lbw_new_int_reg();
			Lbw_build_imm_trans_oper(cb, oper, src0, new_src0);		
		}		
		//process src1	
		if(L_same_operand(src0, oper->dest[0]) && 
								(src1->type == L_OPERAND_IMMED) && 
								SIMM_12(src1->value.i))
		{
			proc_opc = LBWop_INC_IMM12_S;
		}
		else if(bw_is_imm_or_label(src1))
		{
			new_src1 = Lbw_new_int_reg();
			Lbw_build_imm_trans_oper(cb, oper, src1, new_src1);
			proc_opc = oper->opc == Lop_ADD ? LBWop_ADD_S : LBWop_ADD_U;
		}
		else if( bw_is_data_reg(src1) )
		{
			proc_opc = Lop_ADD ? LBWop_ADD_S : LBWop_ADD_U;	
		}
		else
		{
			L_punt("L_annotate_add_INT: error oper %d , the src1 type is not expected", oper->id); 
		}
	}
	else
	{
		L_punt("L_annotate_add_INT: error, oepr %d , the dest operand type is not expected ", oper->id);
	}

	if(new_src0 == NULL)
	{
		new_src0 = L_copy_operand(src0);
	}
	if(new_src1 == NULL)
	{
		new_src1 = L_copy_operand(src1);
	}

	new_oper = L_create_new_op_using(oper->opc, oper);
	new_oper->src[0] = new_src0;
	new_oper->src[1] = new_src1;
	new_oper->dest[0] = L_copy_operand(oper->dest[0]);
	new_oper->proc_opc = proc_opc;
	L_insert_oper_before( cb, oper, new_oper);
}

/*  
	write by ws
*/ 
static void L_annotate_sub_INT(L_Cb * cb, L_Oper * oper)
{
	L_Operand * src0, *src1 ;
	L_Operand *new_src1 = NULL;
	L_Operand *new_src0 = NULL;
	L_Oper * imm_oper = NULL;
	L_Oper * new_oper = NULL;
	int proc_opc = 0;		

	src0 = oper->src[0];
	src1 = oper->src[1];


	if(bw_is_addr_reg( oper->dest[0])  )
	{
		//if the src0 is label and imm
		if(bw_is_imm_or_label(src0) )
		{
			new_src0 = Lbw_new_addr_reg();
			Lbw_build_imm_trans_oper(cb, oper, src0, new_src0);
		}

		if(src1->type == L_OPERAND_IMMED)
		{
			if(SIMM_8(src1->value.i))
			{
				new_src1 = L_copy_operand( src1 );
				new_src1->value.i = new_src1->value.i;
				proc_opc = LBWop_ADD_ADDR_IMM8;
			}
			else
			{
				//we expected the imm_mov oper is reduce by the flowing common_expression reduction
				new_src1 = Lbw_new_addr_reg(); 
				imm_oper = Lbw_build_imm_trans_oper(cb, oper, src1, new_src1);
				imm_oper->src[0]->value.i = (-1)*imm_oper->src[0]->value.i;
				proc_opc = LBWop_ADD_ADDR;
			}
		}
		else if (src1->type == L_OPERAND_LABEL)
		{
			L_punt("L_annotate_sub_INT: error, the src1 is lable , it's terrible ,beacause DSP don'st supported addr substraction , what I can do !?");
		}
		else // addr_reg = addr_reg - addr_reg  is not supported 
		{
			L_punt("L_annotate_sub_INT: the \"addr_reg - addr_reg \" is not expected \n   we should have convert the substruction of pointer to the format in the previouse procedure already!!!");
		}	
	}
	else
	{//the dest is general register 
		//process src0
		if( bw_is_imm_or_label( src0))
		{
			new_src0 = Lbw_new_int_reg();	
			Lbw_build_imm_trans_oper(cb, oper, src0, new_src0) ;
		}
		//process src1	
		if(L_same_operand(src0,oper->dest[0]) && (src1->type == L_OPERAND_IMMED) && SIMM_12(src1->value.i) )
		{
			//the increment operation , need revers the immediate 
			new_src1 = L_copy_operand(src1);
			new_src1->value.i = -(new_src1->value.i);
			proc_opc = LBWop_INC_IMM12_S;
		}
		else if((bw_is_imm_or_label(src1)))
		{
			new_src1 = Lbw_new_int_reg();
			Lbw_build_imm_trans_oper(cb , oper, src1, new_src1);
			proc_opc = oper->opc == Lop_SUB ?  LBWop_SUB_S : LBWop_SUB_U;
		}
		else if(bw_is_data_reg(src1))
		{
			new_src1 = L_copy_operand( src1 ); 
			proc_opc = oper->opc == Lop_SUB ? LBWop_SUB_S : LBWop_SUB_U;
		}
		else
		{
			printf("\n\n");
			L_print_oper(stdout, oper);
			L_punt("L_annotate_sub_INT: error,src1 is  unexpected  operand type: %d ", src1->type);
		}
	}

	if(new_src0 == NULL)
	{
		new_src0 = L_copy_operand(src0);
	}

	if( new_src1 == NULL)
	{
		new_src1 = L_copy_operand(src1);
	}

	new_oper = L_create_new_op_using(oper->opc, oper);
	new_oper->proc_opc = proc_opc; 
	new_oper->src[0] = new_src0;
	new_oper->src[1] = new_src1;
	new_oper->dest[0] = L_copy_operand(oper->dest[0]);
	L_insert_oper_before(cb, oper, new_oper);
	return ;
}

/*check ok*/
static void 
L_annotate_add_sub_F(L_Cb *cb,L_Oper * oper)
{
	L_Oper *new_oper;
	L_Operand *src0 = NULL, *src1 = NULL , *new_src0 = NULL , *new_src1 = NULL;
	int bwop;
  
	src0 = oper->src[0];
	src1 = oper->src[1];

	bwop = (oper->opc==Lop_ADD_F||oper->opc==Lop_ADD_F2)?LBWop_ADD_F:LBWop_SUB_F;
	if( bw_is_addr_reg( src0) || bw_is_addr_reg(src1))
		L_punt("L_annotate_add_sub_F: error %d , the src0 and src1 is expected is the no pointer", oper->id);
		 

	if(src0->type==L_OPERAND_IMMED)
	{
		L_Oper * mov_imm;
		mov_imm = L_create_new_op(Lop_MOV);
		L_add_lineno_attr(mov_imm);
		mov_imm->src[0] = L_copy_operand(src0);
		mov_imm->dest[0] = Lbw_new_float_reg();
		mov_imm->proc_opc = LBWop_MOV_IMM32_F;
		L_insert_oper_before(cb,oper,mov_imm);
		new_src0=L_copy_operand(mov_imm->dest[0]);
	}	

	if(src1->type==L_OPERAND_IMMED)
	{
		L_Oper * mov_imm;
		mov_imm=L_create_new_op(Lop_MOV);
		L_add_lineno_attr(mov_imm);
		mov_imm->src[0]=L_copy_operand(src1);
		mov_imm->dest[0]=Lbw_new_float_reg();
		mov_imm->proc_opc=LBWop_MOV_IMM32_F;
		L_insert_oper_before(cb,oper,mov_imm);
		new_src1=L_copy_operand(mov_imm->dest[0]);
	}
	if(new_src0 == NULL)
		new_src0 = L_copy_operand(oper->src[0]);
	if(new_src1 == NULL)
		new_src1 = L_copy_operand(oper->src[1]);

	new_oper=L_create_new_op_using(oper->opc,oper);
	new_oper->src[0] = new_src0;
	new_oper->src[1] = new_src1;
	new_oper->dest[0] = L_copy_operand(oper->dest[0]);
	new_oper->proc_opc = bwop;
	
	L_insert_oper_before(cb,oper,new_oper);
		return ;	
}

/*****************************************************************************\
 *
 * 							Floating Point Constants
 *
\*****************************************************************************/

static L_Operand *
L_float_constant_immed (L_Cb * cb, L_Oper * oper, L_Operand * src_operand)
{
  L_Oper *new_oper;
  new_oper = L_create_new_op(Lop_MOV_F);
  L_add_lineno_attr(new_oper);
  new_oper->proc_opc = LBWop_MOV_IMM32_F;
  new_oper->src[0] = L_copy_operand (src_operand);

  new_oper->dest[0] = Lbw_new_float_reg();
  L_insert_oper_before (cb, oper, new_oper);

  return (L_copy_operand (new_oper->dest[0]));
}				/* L_float_constant_immed */

/*
 * L_annotate_ld (L_Cb *cb, L_Oper *oper)
 * ----------------------------------------------------------------------
 * note: Load lops form: ld rx = [ry+rz] 
 *                       rx = dest[0],
 *                       ry = src[0] = base,
 *                       rz = src[1] = offset,
 *       Load bw form:  Rs = [Uk+Um,Un]  //Un=0
 *                       Rs = dest[0],
 *                       Uk = src[0] = base,
 *                       Um = src[1] = offset,
 *						 Un = src[2] =word_offset
 10/13/2008  by wxq. 
*/
static void L_annotate_ld (L_Cb * cb, L_Oper * oper)
{
	int bwop = 0;
	L_Oper *new_oper;
	L_Oper *const_oper;
	L_Operand *src0,*src1;
	L_Operand *base_src=NULL,*offset_src=NULL,*word_offset_src;
	
	src0=oper->src[0];
	src1=oper->src[1];
	
	if(Lbw_should_swap_operand(src0,src1))
	{
		src0=oper->src[1];
		src1=oper->src[0];
	}
	
	switch (src0->type)
	{
		case L_OPERAND_IMMED:
		case L_OPERAND_LABEL:
	  		base_src=Lbw_new_addr_reg();
			Lbw_build_imm_trans_oper(cb, oper, src0, base_src);
     		break;

		case L_OPERAND_REGISTER:
		case L_OPERAND_MACRO:
			 base_src=L_copy_operand(src0);
		break;

		default:
			L_punt ("L_annotate_ld:Unknown ld base  type  oper:%d", oper->id);
		return ;
	}

	switch (src1->type)
	{
		case L_OPERAND_IMMED:
			if(SIMM_16(src1->value.i))
	   		{
         			offset_src= L_copy_operand (src1);
	     			bwop=LBWop_LD_IMM16_IMM7;
			}
			else
			{
				offset_src = Lbw_new_addr_reg();
				Lbw_build_imm_trans_oper(cb, oper, src1, offset_src);
				bwop = LBWop_LD_IMM7;
			}
		break;

		case L_OPERAND_MACRO:
		case L_OPERAND_REGISTER:
			if(bw_is_addr_reg(src1))
			{
				offset_src = L_copy_operand(src1);
				bwop=LBWop_LD_IMM7;
			}
			else
			{
				L_punt("L_annotate_ld: the src1 reg is not pointer!!");
	   		}
		break ;
		case L_OPERAND_LABEL:
			offset_src = Lbw_new_addr_reg();
			Lbw_build_imm_trans_oper(cb, oper, src1, offset_src);
			bwop = LBWop_LD_IMM7;
			break;
		default:
			L_punt ("L_annotate_ld:Unknown ld  offset type  oper:%d", oper->id);
	}
	new_oper= L_create_new_op_using(oper->opc, oper);
	new_oper->proc_opc = bwop;
	new_oper->src[0] = base_src;
	new_oper->src[1] = offset_src;
	if(oper->src[2])
		new_oper->src[2] = L_copy_operand(oper->src[2]);
	else
		new_oper->src[2] = L_new_gen_int_operand(0);
	new_oper->dest[0] = L_copy_operand(oper->dest[0]);
	L_insert_oper_before (cb, oper, new_oper);

	if(oper->sync_info != NULL)
	{
		new_oper->sync_info = L_copy_sync_info(oper->sync_info);
		L_add_to_child_list(oper, new_oper);
	}

	if (oper->acc_info)
	{
		new_oper->acc_info = L_copy_mem_acc_spec_list (oper->acc_info);
	}
}



/*
 * L_annotate_st (L_Cb *cb, L_Oper *oper)
 * ----------------------------------------------------------------------
 * note: Store Lops form:  st [rx+ry] = rz
 *                           rx = src[0] = base,
 *                           ry = src[1] = offset,
 *                           rz = src[2] = value to store
 *       Store BW form:  [Uk+Um,Un] = Rs         // Un=0
 *                           Uk = src[0] = base,
 *                           Um = src[1] = offset,
 *                           Un = src[2] =interval  of inter-words,
*                            Rs = src[3] =value ,
 */
/* 10/03/08 */
static void L_annotate_st (L_Cb * cb, L_Oper * oper)
{
  	L_Oper *new_oper = NULL;
  	L_Operand *value_src = NULL,*base_src=NULL,*offset_src=NULL,*word_offset_src=NULL;
  	L_Operand * src0,*src1;
	int bwop; 
	
  	src0=oper->src[0];
  	src1=oper->src[1];
	
	if(Lbw_should_swap_operand(src0,src1))
	{
		src0=oper->src[1];
		src1=oper->src[0];
	}

  	switch (src0->type)
  	{ 
		case L_OPERAND_IMMED:
   		case L_OPERAND_LABEL:
			base_src = Lbw_new_addr_reg();
			Lbw_build_imm_trans_oper(cb, oper, src0, base_src);
		break;

		case L_OPERAND_MACRO:
		case L_OPERAND_REGISTER:
		if(L_is_pointer(src0))
		{
			base_src=L_copy_operand(src0);
		}
		else
		{
			L_punt("L_annotate_st: error , the src0 is expected is pointer");
		}
		break;	
   		default:
			L_punt ("L_annotate_st:Unknown store source type  oper:%d", oper->id);
	}

	switch (src1->type)
	{
		case L_OPERAND_IMMED:
		if (L_is_ctype_integer (src1))
		{
			if(SIMM_16(src1->value.i))
			{
				offset_src= L_copy_operand (src1);
				bwop=LBWop_ST_IMM16_IMM7;
			}
			else if(SIMM_32(src1->value.i))
			{	
				offset_src = Lbw_new_addr_reg();
				Lbw_build_imm_trans_oper(cb, oper, src1, offset_src);
				bwop= LBWop_ST_IMM7;
			}
		} 
		else 
		{
			L_punt ("L_annotate_st:Unknown offset  type  oper:%d", oper->id);
		}
      		break;

		case L_OPERAND_LABEL:
		{
			offset_src = Lbw_new_addr_reg();
			Lbw_build_imm_trans_oper(cb, oper, src1, offset_src);
			bwop = LBWop_ST_IMM7;
		}
		break;
		case L_OPERAND_REGISTER:
		case L_OPERAND_MACRO:
			if(L_is_pointer(src1))
			{	
				bwop=LBWop_ST_IMM7;
				offset_src=L_copy_operand(src1);
			}
			else
	   		{
				L_punt("L_annotate_st: error , the src1 is expected is pointer ");
			}
		 	break;
      		default:
      			L_punt (" L_annotate_st:Unknown store source type  oper:%d", oper->id);
	}

	switch (oper->src[2]->type)
	{
		case L_OPERAND_IMMED:
		{
			value_src = Lbw_new_reg(L_CTYPE_INT);
			Lbw_build_imm_trans_oper(cb, oper, oper->src[2], value_src);	
		} /*if*/
      		break;
	
		case L_OPERAND_LABEL:
		{
			value_src = Lbw_new_int_reg();
			Lbw_build_imm_trans_oper(cb, oper, oper->src[2], value_src);	
		}
			break;

    		case L_OPERAND_REGISTER:
    		case L_OPERAND_MACRO:
	   	if(L_is_pointer(oper->src[2]))
		{
			L_punt("L_annotate_st: error, the src2 is expected not pointer");
		}
		else 
		{
			value_src = L_copy_operand(oper->src[2]);
		}
      		break;
		default:
			L_punt (" L_annotate_st:Unknown store source type  oper:%d", oper->id);
	}/* switch */
   
	new_oper = L_create_new_op_using(oper->opc,oper);
	new_oper->proc_opc = bwop;
	new_oper->src[0] = base_src;
	new_oper->src[1] = offset_src;	
	new_oper->src[2] =L_new_gen_int_operand(0);
	new_oper->src[3] = value_src;	
	L_insert_oper_before (cb, oper, new_oper);
  	if(oper->sync_info != NULL)
	{
		new_oper->sync_info = L_copy_sync_info (oper->sync_info);
		L_add_to_child_list (oper, new_oper);
	}/* if */
	if (oper->acc_info)
	{
		new_oper->acc_info = L_copy_mem_acc_spec_list (oper->acc_info);
	}
}
  
/************************************************************************************
*                                                                                   *
*                           multi  instruction annotatation start      					*
*                                                                                   *
************************************************************************************/

/*11/18/08 by wxq*/
static void
L_annotate_mul_INT (L_Cb * cb, L_Oper * oper)
{
	L_Oper * new_oper;
	L_Operand * src0,*src1,*new_src0,*new_src1;
	int proc_opc;

	src0=oper->src[0];
	src1=oper->src[1];
	if(Lbw_should_swap_operand(src0,src1))
	{
		src0=oper->src[1];
		src1=oper->src[0];
	}
	
	switch(src0->type)
	{
		case L_OPERAND_REGISTER:
		case L_OPERAND_MACRO:
		   new_src0=L_copy_operand(src0);
			break;
		case L_OPERAND_LABEL:
		case L_OPERAND_IMMED:
  	   default:
			L_punt(" L_annotate_mul_INT :unsupport unknown operand type0x%x \
			 ,oper %d\n,",src0->type,oper->id);
	}/* switch(src0->type)*/
	
	switch(src1->type)
	{
		case L_OPERAND_LABEL:
		case L_OPERAND_IMMED:
			new_src1 = Lbw_new_int_reg ();
			Lbw_build_imm_trans_oper (cb, oper,src1,new_src1);
				break;
	  	case L_OPERAND_REGISTER:
		case L_OPERAND_MACRO:
		   new_src1=L_copy_operand(src1);
				break;
      default:
			L_punt(" L_annotate_mul_INT :unsupport unknown operand type %d, oper %d\n,",src1->type,oper->id);
	}/* switch(src1->type)*/
	new_oper = L_create_new_op_using(oper->opc,oper);
	new_oper->src[0] = new_src0;
	new_oper->src[1] = new_src1;
	new_oper->dest[0] = L_copy_operand( oper->dest[0]);

	proc_opc = oper->opc == Lop_MUL ? LBWop_MUL_S : LBWop_MUL_U;
  	new_oper->proc_opc= proc_opc;

	L_insert_oper_before(cb,oper,new_oper);
		return;
}


//check ok
static void L_annotate_mul_F( L_Cb * cb, L_Oper * oper )
{
   
	L_Oper * new_oper;
	L_Operand * src0,*src1,*new_src0,*new_src1;

	src0=oper->src[0];
	src1=oper->src[1];
	if(Lbw_should_swap_operand(src0,src1))
	{
		src0=oper->src[1];
		src1=oper->src[0];
	}

	if( bw_is_addr_reg(src0) || bw_is_addr_reg(src1) )
		L_punt("L_annotate_mul_F : is not expected the src0 or src1 is pointer");

	switch(src0->type)
	{
		case L_OPERAND_LABEL:
		case L_OPERAND_IMMED:
			L_punt(" L_annotate_mul_INT :unsupport imm as the first source operand\
			 ,oper %d\n,",oper->id);
			break;
		case L_OPERAND_REGISTER:
		case L_OPERAND_MACRO:
			new_src0=L_copy_operand(src0);
		break;
		default:
			L_punt(" L_annotate_mul_INT :unsupport operand type yet 0x%x \
			 ,oper %d\n,",src0->type,oper->id);
	}/* switch(src0->type)*/
	
	switch(src1->type)
	{
		case L_OPERAND_IMMED:
			new_src1 = Lbw_new_float_reg(); 
			Lbw_build_imm_trans_oper(cb, oper, src1, new_src1);
			break;
		case L_OPERAND_REGISTER:
		case L_OPERAND_MACRO:
			new_src1=L_copy_operand(src1);
				break;
      default:
			L_punt(" L_annotate_mul_INT :unsupport operand type yet %d, oper %d\n,",src1->type,oper->id);
	}

	new_oper = L_create_new_op_using(oper->opc,oper);
	new_oper->src[0]=new_src0;
	new_oper->src[1]=new_src1;
	new_oper->dest[0]=L_copy_operand(oper->dest[0]);
	new_oper->proc_opc = LBWop_MUL_F;
	L_insert_oper_before(cb,oper,new_oper);
		return;
}

static void L_annotate_int_divide(L_Cb *cb ,L_Oper *oper)
{
	L_Operand *src0, *src1;
	src0 = oper->src[0];
	src1 = oper->src[1];
   if(L_is_pointer(src0)||L_is_pointer(src1))
		L_punt("L_annotate_int_divide:come out the pnt type in oper %d divide\n",oper->id);
	
	  //if two src are constant,then exit
	if(L_is_int_constant (src0) && L_is_int_constant (src1))
		L_punt("L_annotate_int_divide:come out the two constant diviend in oper %d divide\n",oper->id);
	 
	/*assume that src0 is constant,src1 is varibale*/
    if(L_is_int_constant(src0)&&L_is_variable(src1))
	 {
	  L_Oper * mov;
	  L_Operand *constant;

	  constant=L_copy_operand(src0);
	  constant->ctype=L_CTYPE_FLOAT;
      constant->value.f=(float)constant->value.i;
	  mov=L_create_new_op(Lop_MOV);
  	  L_add_lineno_attr(mov);
	  mov->src[0]=constant;
	  mov->dest[0]=Lbw_new_float_reg();
	  mov->proc_opc=LBWop_MOV_IMM32_F;
      L_insert_oper_before(cb,oper,mov);
		
	  L_Oper *i_to_f;
	 
	  i_to_f=L_create_new_op(Lop_I_F);
  	  L_add_lineno_attr(i_to_f);
	  i_to_f->src[0]=L_copy_operand(src1);
	  i_to_f->dest[0]=Lbw_new_float_reg();
	  i_to_f->proc_opc=LBWop_I_F;
	  L_insert_oper_before(cb,oper,i_to_f);
	  		
	  L_Oper *rcp;

	  rcp=L_create_new_op(Lop_RCP_F);
  	  L_add_lineno_attr(rcp);
	  rcp->src[0]=L_copy_operand(i_to_f->dest[0]);
	  rcp->dest[0]=Lbw_new_float_reg();
	  rcp->proc_opc=LBWop_RCP_F;
	  L_insert_oper_before(cb,oper,rcp);
	
      L_Oper *mul_f;
	  mul_f=L_create_new_op(Lop_MUL_F);
  	  L_add_lineno_attr(mul_f);
	  mul_f->src[0]=L_copy_operand(mov->dest[0]);
	  mul_f->src[1]=L_copy_operand(rcp->dest[0]);
	  mul_f->dest[0]=Lbw_new_float_reg();
	  mul_f->proc_opc=LBWop_MUL_F;
	  L_insert_oper_before(cb,oper,mul_f);
	
	  L_Oper *f_to_i;
	  f_to_i=L_create_new_op(Lop_F_I);
  	  L_add_lineno_attr(f_to_i);
      f_to_i->src[0]=L_copy_operand(mul_f->dest[0]);
	  f_to_i->dest[0]=Lbw_new_int_reg();
	  f_to_i->proc_opc=LBWop_F_I;
      L_insert_oper_before(cb,oper,f_to_i);
		
	  L_Oper * mov_result;
	  mov_result=L_create_new_op(Lop_MOV);
  	  L_add_lineno_attr(mov_result);
	  mov_result->src[0]=L_copy_operand(f_to_i->dest[0]);
	  mov_result->dest[0]=L_copy_operand(oper->dest[0]);
	  mov_result->proc_opc=LBWop_MOV_GR;
	  L_insert_oper_before(cb,oper,mov_result);
	
	  return;
	 } 	
	/*assume that src1 is constant,src0 is varibale*/
    if(L_is_int_constant(src1)&&L_is_variable(src0))
	 {
	  L_Oper * mov;
	  L_Operand *constant;

	  constant=L_copy_operand(src1);
	  constant->ctype=L_CTYPE_FLOAT;
      constant->value.f=1/(float)constant->value.i;
	  mov=L_create_new_op(Lop_MOV);
  	  L_add_lineno_attr(mov);
	  mov->src[0]=constant;
	  mov->dest[0]=Lbw_new_float_reg();
	  mov->proc_opc=LBWop_MOV_IMM32_F;
      L_insert_oper_before(cb,oper,mov);
		
	  L_Oper *i_to_f;
	 
	  i_to_f=L_create_new_op(Lop_I_F);
  	  L_add_lineno_attr(i_to_f);
	  i_to_f->src[0]=L_copy_operand(src0);
	  i_to_f->dest[0]=Lbw_new_float_reg();
	  i_to_f->proc_opc=LBWop_I_F;
	  L_insert_oper_before(cb,oper,i_to_f);

      L_Oper *mul_f;
	  mul_f=L_create_new_op(Lop_MUL_F);
  	  L_add_lineno_attr(mul_f);
	  mul_f->src[0]=L_copy_operand(i_to_f->dest[0]);
	  mul_f->src[1]=L_copy_operand(mov->dest[0]);
	  mul_f->dest[0]=Lbw_new_float_reg();
	  mul_f->proc_opc=LBWop_MUL_F;
	  L_insert_oper_before(cb,oper,mul_f);
	
	  L_Oper *f_to_i;
	  f_to_i=L_create_new_op(Lop_F_I);
  	  L_add_lineno_attr(f_to_i);
      f_to_i->src[0]=L_copy_operand(mul_f->dest[0]);
	  f_to_i->dest[0]=Lbw_new_int_reg();
	  f_to_i->proc_opc=LBWop_F_I;
      L_insert_oper_before(cb,oper,f_to_i);

	  L_Oper * mov_result;
	  mov_result=L_create_new_op(Lop_MOV);
  	  L_add_lineno_attr(mov_result);
	  mov_result->src[0]=L_copy_operand(f_to_i->dest[0]);
	  mov_result->dest[0]=L_copy_operand(oper->dest[0]);
	  mov_result->proc_opc=LBWop_MOV_GR;
	  L_insert_oper_before(cb,oper,mov_result);
	
	  return;
	 }
	
    if(L_is_variable(src0)&&L_is_variable(src1))
	{
	  L_Oper *i_to_f_src0;
	 
	  i_to_f_src0=L_create_new_op(Lop_I_F);
  	  L_add_lineno_attr(i_to_f_src0);
	  i_to_f_src0->src[0]=L_copy_operand(src0);
	  i_to_f_src0->dest[0]=Lbw_new_float_reg();
	  i_to_f_src0->proc_opc=LBWop_I_F;
	  L_insert_oper_before(cb,oper,i_to_f_src0);
	
	  L_Oper *i_to_f_src1;
	 
	  i_to_f_src1=L_create_new_op(Lop_I_F);
  	  L_add_lineno_attr(i_to_f_src1);
	  i_to_f_src1->src[0]=L_copy_operand(src1);
	  i_to_f_src1->dest[0]=Lbw_new_float_reg();
	  i_to_f_src1->proc_opc=LBWop_I_F;
	  L_insert_oper_before(cb,oper,i_to_f_src1);
	  		
	  L_Oper *rcp;

	  rcp=L_create_new_op(Lop_RCP_F);
  	  L_add_lineno_attr(rcp);
	  rcp->src[0]=L_copy_operand(i_to_f_src1->dest[0]);
	  rcp->dest[0]=Lbw_new_float_reg();
	  rcp->proc_opc=LBWop_RCP_F;
	  L_insert_oper_before(cb,oper,rcp);
	
      L_Oper *mul_f;
	  mul_f=L_create_new_op(Lop_MUL_F);
  	  L_add_lineno_attr(mul_f);
	  mul_f->src[0]=L_copy_operand(i_to_f_src0->dest[0]);
	  mul_f->src[1]=L_copy_operand(rcp->dest[0]);
	  mul_f->dest[0]=Lbw_new_float_reg();
	  mul_f->proc_opc=LBWop_MUL_F;
	  L_insert_oper_before(cb,oper,mul_f);
	
	  L_Oper *f_to_i;
	  f_to_i=L_create_new_op(Lop_F_I);
  	  L_add_lineno_attr(f_to_i);
      f_to_i->src[0]=L_copy_operand(mul_f->dest[0]);
	  f_to_i->dest[0]=Lbw_new_int_reg();
	  f_to_i->proc_opc=LBWop_F_I;
      L_insert_oper_before(cb,oper,f_to_i);

	  L_Oper * mov_result;
	  mov_result=L_create_new_op(Lop_MOV);
  	  L_add_lineno_attr(mov_result);
	  mov_result->src[0]=L_copy_operand(f_to_i->dest[0]);
	  mov_result->dest[0]=L_copy_operand(oper->dest[0]);
	  mov_result->proc_opc=LBWop_MOV_GR;
	  L_insert_oper_before(cb,oper,mov_result);
	}
return;
}


static void 
L_annotate_rem(L_Cb *cb ,L_Oper *oper)
{
	L_Operand *src0,*src1;
	
	src0=oper->src[0];
	src1=oper->src[1];

	L_Oper *divide;
	int divide_opc;
	if(oper->opc==Lop_REM)
	divide_opc=Lop_DIV;
	else 
	divide_opc=Lop_DIV_U;
	
	divide=L_create_new_op(divide_opc);
  	L_add_lineno_attr(divide);
	divide->src[0]=L_copy_operand(src0);
	divide->src[1]=L_copy_operand(src1);
	divide->dest[0]=Lbw_new_int_reg();
	L_insert_oper_before (cb,oper,divide);
	L_annotate_int_divide(cb,divide);
	
	L_Oper *mul;
	int mul_opc;
	if(oper->opc==Lop_REM)
	mul_opc=Lop_MUL;
	else 
	mul_opc=Lop_MUL_U;
	mul=L_create_new_op(mul_opc);
  	L_add_lineno_attr(mul);
	mul->src[0]=L_copy_operand(divide->dest[0]);
	mul->src[1]=L_copy_operand(src1);
	mul->dest[0]=Lbw_new_int_reg();
	L_insert_oper_before(cb,oper,mul);
	L_annotate_mul_INT(cb,mul);

	L_Oper* sub;
	int sub_opc;
	if(oper->opc==Lop_REM)
	sub_opc=Lop_SUB;
	else 
	sub_opc=Lop_SUB_U;
	
	sub=L_create_new_op(sub_opc);
  	L_add_lineno_attr(sub);
	sub->src[0]=L_copy_operand(src0);
	sub->src[1]=L_copy_operand(mul->dest[0]);
	sub->dest[0]=L_copy_operand(oper->dest[0]);
	L_insert_oper_before(cb,oper,sub);
	L_annotate_sub_INT(cb,sub);

    L_delete_oper (cb,mul);
    L_delete_oper (cb,divide);
	L_delete_oper (cb,sub);

	return;
}

//check ok
static void 
L_annotate_float_divide(L_Cb *cb ,L_Oper *oper)
{
	L_Operand *src0, *src1;
  
	src0 = oper->src[0];
	src1 = oper->src[1];
	
	if(L_is_flt_constant(src0) && L_is_flt_constant (src1))
		L_punt("L_annotate_int_divide:come out the two constant diviend in oper %d divide\n",oper->id);
	 
	/*assume that src0 is constant,src1 is varibale*/
	if(L_is_flt_constant(src0)&&L_is_variable(src1))
	{
		L_Oper * mov;
		L_Operand *constant;
		constant=L_copy_operand(src0);
		mov=L_create_new_op(Lop_MOV);
		L_add_lineno_attr(mov);
		mov->src[0] = constant;
		mov->dest[0] = Lbw_new_float_reg();
		mov->proc_opc = LBWop_MOV_IMM32_F;
		L_insert_oper_before(cb,oper,mov);

		L_Oper *rcp;
		rcp=L_create_new_op(Lop_RCP_F);
		L_add_lineno_attr(rcp);
		rcp->src[0]=L_copy_operand(src1);
		rcp->dest[0]=Lbw_new_float_reg();
		rcp->proc_opc=LBWop_RCP_F;	
		L_insert_oper_before(cb,oper,rcp);
	
      L_Oper *mul_f;
		mul_f=L_create_new_op(Lop_MUL_F);
		L_add_lineno_attr(mul_f);
		mul_f->src[0]=L_copy_operand(mov->dest[0]);
		mul_f->src[1]=L_copy_operand(rcp->dest[0]);
		mul_f->dest[0]=L_copy_operand(oper->dest[0]);
		mul_f->proc_opc=LBWop_MUL_F;
		L_insert_oper_before(cb,oper,mul_f);
		return;
	 } 	
	/*assume that src1 is constant,src0 is varibale*/
    if(L_is_flt_constant(src1)&&L_is_variable(src0))
	 {
	  L_Oper * mov;
	  L_Operand *constant;

	  constant=L_copy_operand(src1);
	  constant->ctype=L_CTYPE_FLOAT;
      constant->value.f=(float)1.0/constant->value.f;
	  mov=L_create_new_op(Lop_MOV);
  	  L_add_lineno_attr(mov);
	  mov->src[0]=constant;
	  mov->dest[0]=Lbw_new_float_reg();
	  mov->proc_opc=LBWop_MOV_IMM32_F;
      L_insert_oper_before(cb,oper,mov);
		
      L_Oper *mul_f;
	  mul_f=L_create_new_op(Lop_MUL_F);
  	  L_add_lineno_attr(mul_f);
	  mul_f->src[0]=L_copy_operand(src0);
	  mul_f->src[1]=L_copy_operand(mov->dest[0]);
	  mul_f->dest[0]=L_copy_operand(oper->dest[0]);
	  mul_f->proc_opc=LBWop_MUL_F;
	  L_insert_oper_before(cb,oper,mul_f);
	  return;
	 }
	
    if(L_is_variable(src0)&&L_is_variable(src1))
	{
	  L_Oper *rcp;

	  rcp=L_create_new_op(Lop_RCP_F);
  	  L_add_lineno_attr(rcp);
	  rcp->src[0]=L_copy_operand(src1);
	  rcp->dest[0]=Lbw_new_float_reg();
	  rcp->proc_opc=LBWop_RCP_F;
	  L_insert_oper_before(cb,oper,rcp);
	
      L_Oper *mul_f;
	  mul_f=L_create_new_op(Lop_MUL_F);
  	  L_add_lineno_attr(mul_f);
	  mul_f->src[0]=L_copy_operand(src0);
	  mul_f->src[1]=L_copy_operand(rcp->dest[0]);
	  mul_f->dest[0]=L_copy_operand(oper->dest[0]);
		mul_f->proc_opc=LBWop_MUL_F;
	  L_insert_oper_before(cb,oper,mul_f);
	
	  return;
	 }
}
/************************************************************************************
*                                                                                   *
*                                  conversion                               	    *
*                                                                                   *
************************************************************************************/
void
L_annotate_float_to_int (L_Cb * cb, L_Oper * oper)
{
	L_Oper * new_oper;
	new_oper=L_create_new_op_using(oper->opc,oper);
	new_oper->src[0]=L_copy_operand(oper->src[0]);
	new_oper->dest[0]=L_copy_operand(oper->dest[0]);
	new_oper->proc_opc=LBWop_F_I;
	L_insert_oper_before(cb,oper,new_oper);
		return ;
}


void L_annotate_int_to_float (L_Cb * cb, L_Oper * oper)
{
		L_Oper * new_oper;
		new_oper=L_create_new_op_using(oper->opc,oper);
		new_oper->src[0]=L_copy_operand(oper->src[0]);
		new_oper->dest[0]=L_copy_operand(oper->dest[0]);
		new_oper->proc_opc=LBWop_I_F;
		L_insert_oper_before(cb,oper,new_oper);
		return ;
}

/************************************************************************************
*                                                                                   *
*                                  logic and shift instr                              	    *
*                                                                                   *
************************************************************************************/

/* Note: bwdsp supported only the instruction that oper->src[1]'s  low 6-bitwise  stand of the 
*num of to shift , so the user of compiler never using shift expression like this:
	int x = 36;
	int a = 1;
	a = a << x;//only mean a = a << (x - 32)
*/
//check ok
static void 
L_annotate_shift(L_Cb * cb, L_Oper *oper)
{
	L_Oper * new_oper;
	L_Operand * src0,*src1,*dest,*new_src0,*new_src1,*new_dest;
	int bwop;

	src0=oper->src[0];
	src1=oper->src[1];
	dest=oper->dest[0];
//first process the src0
	switch(src0->type)
	{
		case L_OPERAND_IMMED:
		{
			L_Oper *mov_imm;
			mov_imm=L_create_new_op(Lop_MOV);
  			L_add_lineno_attr(mov_imm);
			mov_imm->src[0]=L_copy_operand(src0);
			mov_imm->dest[0]=Lbw_new_int_reg();
			if(L_operand_is_signed(src0))
				mov_imm->proc_opc=LBWop_MOV_IMM32_U;
			else
				mov_imm->proc_opc=LBWop_MOV_IMM32_S;
			L_insert_oper_before(cb,oper,mov_imm);
			
			new_src0=L_copy_operand(mov_imm->dest[0]);
		}
			break;

		case L_OPERAND_REGISTER:
		case L_OPERAND_MACRO:
			new_src0=L_copy_operand(src0);
				break;
		default:
			L_punt(" L_annotate_int logic :unsupport operand type yet 0x%x ,oper %d\n,",src0->type,oper->id);
	}

//then process the src1	
	switch(src1->type)
	{
		case L_OPERAND_IMMED:
		if(!SIMM_6(src1->value.i))
			L_punt(" L_annotate_shift:imm should 6bits signed int,oper %d",oper->id);
			switch (oper->opc)
			{
				case  Lop_LSL:
				case  Lop_LSR:
		   		bwop=LBWop_LSHIFT_IMM6;
		   		break;
				case Lop_ASR:
		   		bwop=LBWop_ASHIFT_IMM6;
		   		break;
      		default:
					L_punt(" L_annotate_shift:unexpected opc %d, oper %d\n,",oper->opc,oper->id);
			}
			new_src1=L_copy_operand(src1);
			if(oper->opc==Lop_LSR||oper->opc==Lop_ASR)
				new_src1->value.i=-new_src1->value.i;
			break;
		case L_OPERAND_REGISTER:
		case L_OPERAND_MACRO:
			new_src1=L_copy_operand(src1);
			if(oper->opc==Lop_LSR||oper->opc==Lop_ASR)
			{
				L_Oper * mov_zero;
			  mov_zero=L_create_new_op(Lop_MOV);
  			  L_add_lineno_attr(mov_zero);
			  mov_zero->src[0]=L_new_gen_int_operand(0);
			  mov_zero->dest[0]=Lbw_new_int_reg();
			  mov_zero->proc_opc=LBWop_MOV_IMM32_S;
			
			  L_insert_oper_before(cb,oper,mov_zero);
			
			  L_Oper * sub;
		      
			  int sub_opc;
			  if(L_operand_is_signed(src1))
			  sub_opc=Lop_SUB;
			  else 
			  sub_opc=Lop_SUB_U;

				
			  sub=L_create_new_op(sub_opc);
  			  L_add_lineno_attr(sub);

			  sub->src[0]=L_copy_operand(mov_zero->dest[0]);
			  sub->src[1]=L_copy_operand(src1);
			  sub->dest[0]=Lbw_new_int_reg();
			  if(L_operand_is_signed(src1))
			  sub->proc_opc=LBWop_SUB_S;
			  else 
			  sub->proc_opc=LBWop_SUB_U;
			  
			  L_insert_oper_before(cb,oper,sub);
			  new_src1=L_copy_operand(sub->dest[0]);
				}

			  bwop=LBWop_LSHIFT;
			  if(oper->opc==Lop_ASR)
			  bwop=LBWop_ASHIFT;
			break;
       default:
			L_punt(" L_annotate_shift :unsupport operand type yet %d \
			 ,oper %d\n,",src1->type,oper->id);
		}/* switch(src1->type)*/
	
      
	  new_dest=L_copy_operand(dest);
	  if(L_is_pointer(dest))
		{
		new_dest=Lbw_new_int_reg();
		}

	  new_oper=L_create_new_op_using(oper->opc,oper);
	  new_oper->src[0]=new_src0;
	  new_oper->src[1]=new_src1;
	  new_oper->dest[0]=new_dest;
	  new_oper->proc_opc=bwop;

		L_insert_oper_before(cb,oper,new_oper);
		if(L_is_pointer(dest))
		{
			L_punt("L_annotate_shift: error %d , the dest is not expected the dest is pointer", oper->id);
		}		
		return ;
}

static void L_annotate_int_logic (L_Cb * cb, L_Oper * oper)
{
	int bwop;
	L_Oper * new_oper;
	L_Operand * src0,*src1,*new_src0,*new_src1;

	src0=oper->src[0];
	src1=oper->src[1];

	if(Lbw_should_swap_operand(src0,src1))
   {
		src0=oper->src[1];
		src1=oper->src[0];
	}

	switch(src0->type)
	{
		case L_OPERAND_IMMED:
			L_punt(" L_annotate_int_logic  :unsupport imm as the first source operand, oper %d\n,",oper->id);
			break;
		case L_OPERAND_REGISTER:
		case L_OPERAND_MACRO:
		   new_src0=L_copy_operand(src0);
			break;
		default:
			L_punt(" L_annotate_int logic :unsupport operand type yet 0x%x, oper %d\n,",src0->type,oper->id);
	}
	
	switch(src1->type)
	{
		case L_OPERAND_IMMED:
			new_src1 = Lbw_new_int_reg();
			L_Oper *mov = Lbw_build_imm_trans_oper(cb,oper,src1,new_src1);
			L_insert_oper_before(cb, oper, mov);
				break;
		case L_OPERAND_REGISTER:
		case L_OPERAND_MACRO:
			new_src1 = L_copy_operand(src1);
				break;
      default:
			L_punt(" L_annotate_int_logic :unsupport operand type yet %d \
			 ,oper %d\n,",src1->type,oper->id);
	}
	switch (oper->opc)
	{
		case  Lop_AND:
		   bwop=LBWop_AND;
		   break;
		case Lop_OR:
		   bwop=LBWop_OR;
		   break;
		case Lop_NOR:
			bwop = LBWop_NOR;
			break;
   	case Lop_NAND:
			bwop = LBWop_NAND;
			break;
    	case Lop_XOR:
		   bwop=LBWop_XOR;
		   break;	 
      default:
			L_punt(" L_annotate_int_logic :unsupport operand type yet %d,oper %d\n,",src1->type,oper->id);

	}
	  new_oper=L_create_new_op_using(oper->opc,oper);
	  new_oper->src[0]=new_src0;
	  new_oper->src[1]=new_src1;
	  new_oper->dest[0]=L_copy_operand(oper->dest[0]);
	  new_oper->proc_opc=bwop;
	  L_insert_oper_before(cb,oper,new_oper);
	  return;
}








/************************************************************************************
*                                                                                   *
*                                  call conventions                                 *
*                                                                                   *
************************************************************************************/


static void
L_annotate_jsr (L_Func * fn, L_Cb * cb, L_Oper * oper)
{
	L_Oper *jsr_oper = NULL,*mov_reg_sr = NULL;
	L_Operand * new_src = NULL;
	int proc_opc = 0;
	L_Attr *attr;

	switch (oper->src[0]->type)
	{
		case L_OPERAND_LABEL:

			if( L_EXTRACT_BIT_VAL ( oper->flags, OP_FLAG_SYNC))
				jsr_oper = L_create_new_op_using (Lop_JSR_ND, oper);
			else
				jsr_oper = L_create_new_op_using (Lop_JSR, oper);

			proc_opc = LBWop_JSR;	
			break;

		case L_OPERAND_REGISTER:
		case L_OPERAND_MACRO:
		{
			if( oper->src[0]->ctype == L_CTYPE_POINTER)
				L_punt("L_annotate_jsr: error, the jsr expected the src_operand is no pointer");
			mov_reg_sr = L_create_new_op(Lop_MOV);
			mov_reg_sr->proc_opc = LBWop_MOV_GR_SR;
			mov_reg_sr->src[0] = L_copy_operand(oper->src[0]);
			mov_reg_sr->dest[0] = Lbw_MAC_SR(SR);
			L_insert_oper_before(cb,oper,mov_reg_sr);
			proc_opc = LBWop_JSR_SR;
			break;
		}
      default:
			L_punt(" L_annotate_jsr :unsupport oper %d\n,",oper->id);
	}

	if( jsr_oper == NULL)
	{
		jsr_oper = L_create_new_op_using(Lop_JSR, oper);
	}
	jsr_oper->proc_opc = proc_opc; 

	if( new_src == NULL)
	{
		new_src = L_copy_operand(oper->src[0]);
	}

	jsr_oper->src[0] = new_src;
	L_insert_oper_before(cb, oper, jsr_oper);

	if (jsr_oper && oper->sync_info)
	{
		jsr_oper->sync_info = L_copy_sync_info (oper->sync_info);
		L_add_to_child_list (oper, jsr_oper);
	}				/* if */

	if (jsr_oper && oper->acc_info)
		jsr_oper->acc_info = L_copy_mem_acc_spec_list (oper->acc_info);

	return;

}


static void
L_annotate_rts (L_Cb * cb, L_Oper * oper)
{
	L_Oper *rts_oper;

	rts_oper = L_create_new_op_using (Lop_RTS, oper);
	rts_oper->proc_opc = LBWop_RTS;
	//rts_oper->src[0] = Ltahoe_BMAC(RETADDR);
	L_insert_oper_before (cb, oper, rts_oper);

	if (oper->sync_info != NULL)	
	{
		rts_oper->sync_info = L_copy_sync_info (oper->sync_info);	
		L_add_to_child_list (oper, rts_oper);
	}				/* if */

	if (oper->acc_info)
		rts_oper->acc_info = L_copy_mem_acc_spec_list (oper->acc_info);

	return;

}

static void
L_annotate_jump (L_Cb * cb, L_Oper * oper)
{
  L_Oper *jump_oper;

  jump_oper = L_create_new_op_using (Lop_JUMP, oper);
  jump_oper->proc_opc = LBWop_JUMP;
  jump_oper->src[0] = L_copy_operand (oper->src[0]);
  L_insert_oper_before (cb, oper, jump_oper);

  return;
}				/* L_annotate_jump */


static void
L_annotate_prologue (L_Func * fn, L_Cb * cb, L_Oper * oper)
{
	L_Oper *new_oper, *alloc_oper, *mov_oper;
	int leaf;

	leaf = L_EXTRACT_BIT_VAL (fn->flags, L_FUNC_LEAF);

	/* Record if function is leaf */
	new_oper = L_create_new_op_using (Lop_DEFINE, oper);
	new_oper->proc_opc = LBWop_NON_INSTR;
    new_oper->dest[0] = L_new_gen_int_operand (-1); 
	new_oper->src[0] = L_new_gen_int_operand (leaf);
	L_insert_oper_before (cb, oper, new_oper);


/****		GP, global data pointer	***************


	new_oper = L_create_new_op_using (Lop_DEFINE, oper);
	new_oper->proc_opc = TAHOEop_NON_INSTR;
	new_oper->dest[0] = Ltahoe_IMAC (GP);
	L_insert_oper_before (cb, oper, new_oper);


*********************************************************/


	/*  Mark prologue as non-Tahoe instruction  */
   //	oper->proc_opc = LBWop_NON_INSTR;
	// L_insert_oper_before (cb, oper, L_copy_parent_oper (oper));

	/* Tahoe alloc instruction */
	 alloc_oper = L_create_new_op_using (Lop_ALLOC, oper);
	//alloc_oper->proc_opc = TAHOEop_ALLOC;
	 //alloc_oper->dest[0] = Ltahoe_new_int_reg ();
	//pfs_save_operand = alloc_oper->dest[0];
	
	alloc_oper->src[0] = L_new_gen_int_operand (-1);
	alloc_oper->src[1] = L_new_gen_int_operand (-1);
	alloc_oper->src[2] = L_new_gen_int_operand (-1);
	alloc_oper->src[3] = L_new_gen_int_operand (-1);
	alloc_oper->proc_opc=LBWop_NON_INSTR;
    L_insert_oper_before(cb, oper, alloc_oper);
	return;
}



static void
L_annotate_epilogue (L_Func * fn, L_Cb * cb, L_Oper * oper)
{
	L_Oper *new_oper, *def_oper;
	int leaf;


	/*  Mark epilogue as non-Tahoe instruction  */

	oper->proc_opc = LBWop_NON_INSTR;
	new_oper = L_copy_parent_oper (oper);
	L_insert_oper_before (cb, oper, new_oper);



			
/****		GP, global data pointer	***************

	def_oper = L_create_new_op (Lop_DEFINE);
	def_oper->proc_opc = TAHOEop_NON_INSTR;
	def_oper->src[0] = Ltahoe_IMAC (GP);
	L_insert_oper_after (cb, new_oper, def_oper);

*********************************************************/

  return;

}

//check ok
static void L_annotate_br (L_Cb *cb, L_Oper * oper)
{
      int i;
      L_Oper * new_oper;
		L_Operand *src0, *src1,*src2;
		L_Operand *new_src0 = NULL , *new_src1 = NULL ,*new_src2 = NULL;

      new_oper = L_create_new_op_using (oper->opc, oper);
//process proc_opc
      if( oper->com[0]== L_CTYPE_INT
			|| oper->com[0]==L_CTYPE_LONG
			|| oper->com[0]==L_CTYPE_CHAR
			|| oper->com[0]==L_CTYPE_SHORT
			|| oper->com[0]==L_CTYPE_LONG
         || oper->com[0]== L_CTYPE_LLONG)
		{

            new_oper->proc_opc = LBWop_COMB_S;
		}
      else if( oper->com[0] == L_CTYPE_UINT 
					|| oper->com[0] == L_CTYPE_CHAR
            	|| oper->com[0] == L_CTYPE_ULONG
					|| oper->com[0] == L_CTYPE_ULLONG
					|| oper->com[0] == L_CTYPE_UCHAR
					|| oper->com[0] == L_CTYPE_USHORT)
		{
			new_oper->proc_opc = LBWop_COMB_U;
		}
      else if( oper->com[0] == L_CTYPE_FLOAT
              || oper->com[0] == L_CTYPE_DOUBLE)
		{
            new_oper->proc_opc = LBWop_COMB_F;
		}
		else
		{
			L_punt("L_annoate_br : bad compare operand_type,type is %d\n",oper->com[0]);
		}

		new_oper->com[0] = oper->com[0];
		new_oper->com[1] = oper->com[1];

//process operand
		src0 = oper->src[0];
		src1 = oper->src[1];

		if(src0->type == L_OPERAND_IMMED)
		{
			
			new_src0 = Lbw_new_reg( src0->ctype );
			Lbw_build_imm_trans_oper(cb, oper, src0, new_src0);
		}

		if(bw_is_addr_reg(src0))
		{
			L_punt("L_annotate_br: error, op %d the src operand is addr register", oper->id);
		}

		if(src1->type == L_OPERAND_IMMED)
		{
			new_src1 = Lbw_new_int_reg();
			Lbw_build_imm_trans_oper(cb, oper, src1, new_src1);
		}

     	if(bw_is_addr_reg(src1))
		{
			L_punt("L_annotate_br: error, op %d the src1 is not general_register");
		}
		if(new_src0 == NULL)
			new_src0 = L_copy_operand(src0);
		if(new_src1 == NULL)
			new_src1 = L_copy_operand(src1);

		new_oper->src[0]=new_src0;
		new_oper->src[1]=new_src1;
		new_oper->src[2]= L_copy_operand(oper->src[2]);
		L_insert_oper_before(cb,oper,new_oper);
}




static void L_check_lineno_attr(L_Attr *oper_attr)
{
	
	if(DEBUG)
	{
		if((lineno_attr=L_find_attr(oper_attr,"lineno"))==NULL)
		{
			L_punt("the current oper does't have lineno attr \n");
		}	
	}
}

void L_convert_to_bw_oper (L_Func * fn, L_Cb * cb, L_Oper * oper)
{
   L_check_lineno_attr(oper->attr);
	
	int opc;
	int i;
	L_Operand *mac_opd;
	L_Oper *new_oper;
   L_Operand * mac_addr;
/*
*	operation  that  one of source oprands is Macro and the opc is some opc
*  that is not opc-add  . convert this operation  to add or add and another opcs 
*  example : load [r0-dest] [macro-src1, const-src2]
*  --> add [r1-dest][macro-src1,const-src(0)] ; load[r0-dest] [r1-dest, const-src2]
*  because utilizy about the stack memory ,only can use is add  operation  with stack pointer;
*	so no add opcis not ok for stack pointer parameter; 
*/
	for (i = 0; i < L_max_src_operand; i++)
	{
		if(L_is_macro (oper->src[i]) &&
		((oper->src[i]->value.mac == L_MAC_OP) ||
		(oper->src[i]->value.mac == L_MAC_IP) ||
		(oper->src[i]->value.mac == L_MAC_LV) ||
		(oper->src[i]->value.mac == L_MAC_SP) ||
		(oper->src[i]->value.mac == L_MAC_FP)))

			 mac_opd = oper->src[i];
		else
			continue;
		if (oper->opc == Lop_DEFINE)
		continue;
		else if (oper->opc == Lop_MOV)
		{
		    // Turn a MOV into a constant add 
		    oper->opc = Lop_ADD;
		    oper->src[1] = oper->src[0];
		    oper->src[0] = L_new_gen_int_operand (0);
		    break;
		}/* else if */
		else
		{
		    //  Insert a constant add prior to the op 
		    new_oper = L_create_new_op_using (Lop_ADD, oper);
		    new_oper->src[0] = mac_opd;
		    new_oper->src[1] = L_new_gen_int_operand (0);
		    new_oper->dest[0] = L_new_register_operand (++(L_fn->max_reg_id), 
					       L_CTYPE_POINTER, 0);
		    oper->src[i] = L_copy_operand (new_oper->dest[0]);
		    L_insert_oper_before (cb, oper, new_oper);
		    L_annotate_add_INT (cb,new_oper);
		    L_delete_oper (cb, new_oper);
  		}
	} 

	opc = oper->opc;
switch (opc)
{
    case Lop_NO_OP:
      L_annotate_same(cb, oper);
      break;
    case Lop_JSR:
    case Lop_JSR_FS:
      L_annotate_jsr(fn,cb,oper);
      break;
    case Lop_RTS:
    case Lop_RTS_FS:
      L_annotate_rts(cb,oper);
      break;
    case Lop_JUMP:
    case Lop_JUMP_FS:
      L_annotate_jump (cb, oper);      
      break;
    case Lop_PROLOGUE:
      L_annotate_prologue(fn,cb, oper);
      break;
    case Lop_EPILOGUE:
      L_annotate_epilogue(fn,cb, oper);
      break;
    case Lop_DEFINE:
    	L_annotate_define(cb, oper);
    	/*
      oper->proc_opc = LBWop_NON_INSTR;
      L_insert_oper_before (cb, oper, L_copy_parent_oper (oper));
      */
      break;
    /*case Lop_PRED_CLEAR:
    case Lop_PRED_SET:
    case Lop_PRED_COPY:
      L_annotate_same(cb, oper);
      break;
    case Lop_LD_POST_UC:
    case Lop_LD_POST_C:
    case Lop_LD_POST_UC2:
    case Lop_LD_POST_C2:
    case Lop_LD_POST_F:
    case Lop_LD_POST_F2:
    case Lop_LD_POST_I:
    case Lop_LD_POST_UI:
    case Lop_LD_UC_CHK:
    case Lop_LD_C_CHK:
    case Lop_LD_UC2_CHK:
    case Lop_LD_C2_CHK:
    case Lop_LD_I_CHK:
    case Lop_LD_UI_CHK:
    case Lop_LD_F_CHK:
    case Lop_LD_F2_CHK:
      L_annotate_same (cb, oper);
      break;*/
    case Lop_LD_UC:
    case Lop_LD_C:
    case Lop_LD_UC2:
    case Lop_LD_C2:
    case Lop_LD_F:
    case Lop_LD_I:
    case Lop_LD_UI:
	 case Lop_LD_F2:
    case Lop_LD_Q:
      L_annotate_ld(cb,oper);
	  break;
   /* case Lop_ST_POST_C:
    case Lop_ST_POST_C2:
    case Lop_ST_POST_I:
    case Lop_ST_POST_F:
    case Lop_ST_POST_F2:
      L_annotate_same (cb, oper);
      break;*/
     case Lop_ST_C:
     case Lop_ST_C2:
	  case Lop_ST_I:
     case Lop_ST_F:
     case Lop_ST_F2:
	  case Lop_ST_Q:
	  L_annotate_st(cb,oper);
	   break;
  case Lop_SXT_I:
  case Lop_ZXT_I:
	  L_punt("L_annotate_extend is needed ");
       // L_annotate_extend(cb,oper);
      break;
     case Lop_MOV:
       L_annotate_move(cb,oper);
      break;
    case Lop_ADD:
    case Lop_ADD_U:
      L_annotate_add_INT(cb, oper); 
      break;
    case Lop_SUB:
    case Lop_SUB_U:
      L_annotate_sub_INT(cb, oper); 
      break;
    case Lop_AND:
    case Lop_NAND:
    case Lop_OR:
    case Lop_NOR:
    case Lop_XOR:
	  L_annotate_int_logic (cb,oper);
		break;
    case Lop_NXOR:
		   L_punt(" L_annotate_int_logic :come out Lop_NXOR %d, oper %d,",oper->opc,oper->id);
		break;
    case Lop_AND_COMPL:
    case Lop_OR_COMPL:
		   L_punt(" L_annotate_int_logic :unexpected opc %d, oper %d\n,",oper->opc,oper->id);
      break;
    case Lop_MUL:
    case Lop_MUL_U:
	  L_annotate_mul_INT (cb,oper);
      break;
    case Lop_DIV:
    case Lop_DIV_U:
	  L_annotate_int_divide(cb,oper);
     //L_warn ("warn:div come out , oper %d", oper->id);
      break;
    case Lop_DIV_F:
    case Lop_DIV_F2:
	  L_annotate_float_divide(cb,oper);
     // L_warn ("warn:div-f come out , oper %d", oper->id);
	 break;
    case Lop_REM:
    case Lop_REM_U:
      L_annotate_rem(cb, oper);
      break;
    case Lop_MOV_F:
    case Lop_F_F2:
    case Lop_F2_F:
    case Lop_MOV_F2:
      L_annotate_move(cb, oper);
      break;
    case Lop_ADD_F:
    case Lop_ADD_F2:
    case Lop_SUB_F:
    case Lop_SUB_F2:
      L_annotate_add_sub_F(cb, oper);
      break;
    case Lop_MUL_F2:
    case Lop_MUL_F:
      L_annotate_mul_F(cb,oper);
      break;
    case Lop_F2_I:
    case Lop_F_I:
	  L_annotate_float_to_int (cb, oper);
      break;
    case Lop_I_F2:
    case Lop_I_F:
	  L_annotate_int_to_float (cb,oper);
      break;
    case Lop_LSR:
    case Lop_LSL:
    case Lop_ASR:
      L_annotate_shift(cb, oper);
      break;
    case Lop_LSLADD:
      L_punt ("warn:come out the instruction Lop_LSLADD ,oper %d", oper->id);
      break;
    case Lop_EXTRACT:
    case Lop_EXTRACT_U:
      L_annotate_same(cb, oper);
      break;
    case Lop_DEPOSIT:
      L_annotate_same(cb, oper);
      break;
    case Lop_ABS:
    case Lop_ABS_F:
      L_punt ("come out the instruction Lop_ABS_F, oper %d", oper->id);
	  break;
    case Lop_ABS_F2:
      L_punt ("ABS on the F2, oper %d", oper->id);
      break;
    case Lop_MAX_F:
    case Lop_MIN_F:
      L_punt ("come out MAX_F/MIN_F,oper %d", oper->id);
	  break;
    case Lop_MIN_F2:
    case Lop_MAX_F2:
	  L_punt ("MAX/MIN on the F2, oper %d", oper->id);
      break;
    case Lop_RCP_F:
    case Lop_SQRT_F:
	  L_punt ("come out RCP_F/SQRT_F, oper %d", oper->id);
      break;
    case Lop_RCP_F2:
    case Lop_SQRT_F2:
	  L_punt ("RCP/SQRT on the F2, oper %d", oper->id);
      break;
    case Lop_BR:     //here the BR is not PBR , modified by wansheg@mail.ustc.edu.cn
	   L_annotate_br(cb, oper);
      break;
    case Lop_ALLOC:
      L_punt ("L_convert_to_bw_oper: should not encounter Lop_ALLOC");
      break;
    case Lop_JUMP_RG:
    case Lop_JUMP_RG_FS:
      L_punt ("L_convert_to_bw_oper: come out the JUMP_RG");
      break;
    case Lop_RCMP:
    case Lop_RCMP_F:
		L_punt("Lop_RCMP/Lop_RCMP_F: it is expected the RCMP is convert to contral flow");
	  break;
	case Lop_INTRINSIC:
		//L_annotate_intrinsic(cb,oper);
		L_punt("intrinsic is not supported now ");
		break;
    case Lop_MUL_ADD:
    case Lop_MUL_ADD_U:
    case Lop_MUL_SUB:
    case Lop_MUL_SUB_U:
    case Lop_MUL_SUB_REV:
    case Lop_MUL_SUB_REV_U:
    case Lop_LD_PRE_UC:
    case Lop_LD_PRE_C:
    case Lop_LD_PRE_UC2:
    case Lop_LD_PRE_C2:
    case Lop_LD_PRE_F:
    case Lop_LD_PRE_F2:
    case Lop_LD_PRE_I:
    case Lop_LD_PRE_UI:
    case Lop_ST_PRE_C:
    case Lop_ST_PRE_C2:
    case Lop_ST_PRE_I:
    case Lop_ST_PRE_F:
    case Lop_ST_PRE_F2:
    case Lop_BIT_EXTRACT:
    case Lop_BIT_DEPOSIT:
    case Lop_AND_NOT:
    case Lop_OR_NOT:
    case Lop_MAX:
    case Lop_MIN:
    case Lop_REV:
    case Lop_BIT_POS:
    case Lop_PRED_LD:
    case Lop_PRED_ST:
    case Lop_PRED_LD_BLK:
    case Lop_PRED_ST_BLK:
    case Lop_PRED_MERGE:
    case Lop_FETCH_AND_ADD:
    case Lop_FETCH_AND_OR:
    case Lop_FETCH_AND_AND:
    case Lop_FETCH_AND_ST:
    case Lop_FETCH_AND_COND_ST:
    case Lop_ADVANCE:
    case Lop_AWAIT:
    case Lop_MUTEX_B:
    case Lop_MUTEX_E:
    case Lop_CO_PROC:
    case Lop_CONFIRM:
    case Lop_PREF_LD:
    case Lop_EXPAND:
    case Lop_SIM_DIR:
    case Lop_CMOV:
    case Lop_CMOV_COM:
    case Lop_CMOV_F:
    case Lop_CMOV_COM_F:
    case Lop_CMOV_F2:
    case Lop_CMOV_COM_F2:
    case Lop_SELECT:
    case Lop_SELECT_F:
    case Lop_SELECT_F2:
    case Lop_JSR_ND:
	           
    
    case Lop_LD_POST_UC:
    case Lop_LD_POST_C:
    case Lop_LD_POST_UC2:
    case Lop_LD_POST_C2:
    case Lop_LD_POST_F:
    case Lop_LD_POST_F2:
    case Lop_LD_POST_I:
    case Lop_LD_POST_UI:
    case Lop_LD_UC_CHK:
    case Lop_LD_C_CHK:
    case Lop_LD_UC2_CHK:
    case Lop_LD_C2_CHK:
    case Lop_LD_I_CHK:
    case Lop_LD_UI_CHK:
    case Lop_LD_F_CHK:
    case Lop_LD_F2_CHK:
	
    case Lop_ST_POST_C:
    case Lop_ST_POST_C2:
    case Lop_ST_POST_I:
    case Lop_ST_POST_F:
    case Lop_ST_POST_F2:
	
    case Lop_PRED_CLEAR:
    case Lop_PRED_SET:
    case Lop_PRED_COPY:
    case Lop_MUL_ADD_F:
    case Lop_MUL_ADD_F2:
	case Lop_CHECK:
	case Lop_MUL_SUB_F:
	case Lop_MUL_SUB_F2:
	case Lop_MUL_SUB_REV_F:
	case Lop_MUL_SUB_REV_F2:
	case Lop_ZXT_C2://sxt ,sign number extend instruction 
	case Lop_SXT_C2:
	case Lop_EXTRACT_C2:
	case Lop_ZXT_C:
	case Lop_EXTRACT_C:
	case Lop_SXT_C:

	default:
		L_print_oper (stdout, oper);
		L_punt ("L_convert_to_bw_oper: unsupported Lcode opcode!");
	break;
}//switch
}

/* Determines if function is a leaf (has no callees), and marks it accordingly.
 */

static int L_leaf_func (L_Func * fn)
{
	L_Oper *oper;
	L_Cb *cb;
	int leaf;
	leaf = TRUE;
	for (cb = fn->first_cb; cb && leaf; cb = cb->next_cb)
	{
      for (oper = cb->first_op; oper; oper = oper->next_op)
		{
	  		if ((oper->opc == Lop_JSR) ||
	     		 (oper->opc == Lop_JSR_FS) || (oper->opc == Lop_JSR_ND))
	    	{
				if (L_is_label (oper->src[0]))
				{
		  			if(!strcmp (oper->src[0]->value.l, "_$fn_alloca") ||
						!strcmp (oper->src[0]->value.l, "_$fn_abs"))
		    			continue;
				}		/* if */
	      	leaf = FALSE;
	      		break;
			}/* if */
		}/* for oper */
	}/* for cb */
	if (leaf == TRUE)
   	fn->flags = L_SET_BIT_FLAG (fn->flags, L_FUNC_LEAF);
	if ((leaf == FALSE) && L_EXTRACT_BIT_VAL (fn->flags, L_FUNC_LEAF))
		L_punt ("L_leaf_func: leaf flag set but there is a jsr");
	else if ((leaf == TRUE) && !L_EXTRACT_BIT_VAL (fn->flags, L_FUNC_LEAF))
		L_punt ("L_leaf_func: leaf flag not set and no jsr in fucntion");
	return (leaf);
}				/* L_leaf_func */


void L_process_func (L_Func * fn)
{
	L_Oper *oper;
	L_Cb *cb;
	char  debug=0;
	pre_process_func(fn);
/*
  	printf("\n+++++++++++++++++++after pre_process the Lfun+++++++++++++++++++++++ \n\n");
	L_print_func(stdout,fn);
*/
	int do_addr_opti = 1;
	if(do_addr_opti)
	{	
		L_optimize_addr_reg(fn); 	
	}
	else
	{
		L_simple_distinguish_addr(fn);
	}
	
	before_annotate_test(fn);
#if 0
  	printf("\n+++++++++++++++++++after addr_reg process  the Lfun+++++++++++++++++++++++ \n\n");
	L_print_func(stdout,fn);
#endif

	L_leaf_func (fn);
	L_init_child_list(fn);
	L_mcode_init_function ();

  	for (cb = fn->first_cb; cb; cb = cb->next_cb)
	{
		oper = cb->first_op;
		while (oper)
		{
			L_convert_to_bw_oper (fn, cb, oper);
			oper = bw_convert_to_parent(cb, oper);
		}
	}
	L_relink_child_sync_arcs(fn);
	L_deinit_child_list(fn);
#if 1
	printf("------------------------- after  instruction annotate ---------------------------------------------\n");
	L_print_func(stdout, fn);
#endif
}


